//
//  APTagsFlowLayout.swift
//  APSwift
//
//  Created by jianbo.pei on 2022/9/13.
//

import UIKit

class APTagsFlowLayout: UICollectionViewFlowLayout {
    
    public weak var delegate: UICollectionViewDelegateFlowLayout?
    private var layoutAttributesArray: [UICollectionViewLayoutAttributes] = []
    private var contentHeight: CGFloat = 0.0

    override init() {
        super.init()
        scrollDirection = .vertical
        minimumLineSpacing = 5
        minimumInteritemSpacing = 5
        sectionInset = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    private func minimumInteritemSpacing(at section: Int) -> CGFloat {
        if let collectionV = collectionView, let spacing = delegate?.collectionView?(collectionV, layout: self, minimumInteritemSpacingForSectionAt: section) {
            return spacing
        } else {
            return minimumInteritemSpacing
        }
    }
    
    private func minimumLineSpacing(at section: Int) -> CGFloat {
        if let collectionV = collectionView, let spacing = delegate?.collectionView?(collectionV, layout: self, minimumLineSpacingForSectionAt: section) {
            return spacing
        } else {
            return minimumLineSpacing
        }
    }
    
    private func sectionInset(at section: Int) -> UIEdgeInsets {
        if let collectionV = collectionView, let inset = delegate?.collectionView?(collectionV, layout: self, insetForSectionAt: section) {
            return inset
        } else {
            return sectionInset
        }
    }
    
}

extension APTagsFlowLayout {
    override func prepare() {
        super.prepare()
        
        let itemCount = collectionView?.numberOfItems(inSection: 0) ?? 0
        let minInteritemSpacing = minimumInteritemSpacing(at: 0)
        let minLineSpacing = minimumLineSpacing(at: 0)
        let sectionInset = sectionInset(at: 0)
        
//        CGFloat xOffset = sectionInset.left;
//        CGFloat yOffset = sectionInset.top;
//        CGFloat xNextOffset = sectionInset.left;
//        CGRect colloctionViewBounds = [self collectionView].bounds;
        
        var xOffset = sectionInset.left
        var yOffset = sectionInset.top
        var xNextOffset = sectionInset.left
        let colloctionViewBounds = collectionView?.bounds ?? .zero
        
        for idx in 0..<itemCount {
            let indexPath = IndexPath(item: idx, section: 0)
            let itemSize = itemSize(at: indexPath)
            xNextOffset += (minInteritemSpacing + itemSize.width)
            if xNextOffset - minInteritemSpacing > colloctionViewBounds.size.width - sectionInset.right {
                xOffset = sectionInset.left
                xNextOffset = sectionInset.left + minInteritemSpacing + itemSize.width
                yOffset += (itemSize.height + minLineSpacing)
            } else {
                xOffset = xNextOffset - (minInteritemSpacing + itemSize.width)
            }
            
            let layoutAttributes = UICollectionViewLayoutAttributes(forCellWith: indexPath)
            layoutAttributes.frame = CGRect(x: xOffset, y: yOffset, width: itemSize.width, height: itemSize.height)
            layoutAttributesArray.append(layoutAttributes)
            
            contentHeight = max(contentHeight, layoutAttributes.frame.maxY)
        }
        
        contentHeight += sectionInset.bottom
    }
    
    private func itemSize(at indexPath: IndexPath) -> CGSize {
        if let collectionV = collectionView, let size = delegate?.collectionView?(collectionV, layout: self, sizeForItemAt: indexPath) {
            return size
        } else {
            return .zero
        }
    }
    
    override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
        return layoutAttributesArray.filter { layoutAttributes in
            return rect.intersects(layoutAttributes.frame)
        }
    }
    
    override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
        if layoutAttributesArray.count > indexPath.item {
            return layoutAttributesArray[indexPath.item]
        } else {
            return nil
        }
    }
    
    override var collectionViewContentSize: CGSize {
        get {
            prepare()
            let contentSize = CGSize(width: collectionView?.frame.size.width ?? 0, height: contentHeight)
            return contentSize
        }
    }
    
    override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
        let oldBounds = collectionView?.bounds ?? .zero
        if oldBounds.size.equalTo(newBounds.size) {
            return true
        } else {
            return false
        }
    }
}
